import { Command } from "commander";
import { EslintPluginController } from "./Controller.js";

// 定义控制器方法名称枚举
enum ControllerMethodNames {
  PathConfirm = "onPathConfirm",
  WorkspaceConfirm = "onWorkspaceConfirm",
  DependenciesClean = "onDependenciesClean",
  ConfigFilesClean = "onConfigFilesClean",
  PackageScriptsUpdate = "onPackageScriptsUpdate",
  DependenciesInstall = "onDependenciesInstall",
}

/**
 * eslint-plugin 命令执行函数
 * 使用流程化的方式执行各个步骤
 */
export async function eslintPluginCommand(args: object, command: Command) {
  const controller = new EslintPluginController();
  let projectType: string;

  try {
    // 定义执行流程
    const bindControllerMethods = (
      controller: EslintPluginController,
      methodNames: Array<keyof typeof EslintPluginController.prototype>
    ) => {
      return methodNames.map((methodName) =>
        controller[methodName].bind(controller)
      );
    };

    const EslintPluginCommandFlows = [
      // 验证阶段
      async () => {
        projectType = (await controller.onCommandConfirm(
          args,
          command
        )) as unknown as string;
      },
      ...bindControllerMethods(controller, [
        ControllerMethodNames.PathConfirm,
        ControllerMethodNames.WorkspaceConfirm,
        ControllerMethodNames.DependenciesClean,
        ControllerMethodNames.ConfigFilesClean,
      ]),
      // 创建阶段
      async () => {
        await controller.onConfigFilesCreate(projectType);
      },
      ...bindControllerMethods(controller, [
        ControllerMethodNames.PackageScriptsUpdate,
        ControllerMethodNames.DependenciesInstall,
      ]),
    ];

    // 使用 reduce 串行执行所有流程
    await EslintPluginCommandFlows.reduce(async (promise, flow) => {
      await promise;
      await flow(args as never, command);
      return Promise.resolve();
    }, Promise.resolve());

    // 询问是否执行验证
    const shouldVerify = await controller.askForVerification();
    if (shouldVerify) {
      await controller.onEslintVerification();
      await controller.onChangesCommit();
    }

    // 显示执行结果表格
    controller.displayResultTable();
  } catch (error) {
    // 发生错误时也显示执行结果表格
    controller.displayResultTable();
  }
}
